import java.awt.Color;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JLabel;

/**
 * TODO:
 * Implement custom mass
 */
public class World extends JFrame implements KeyListener
{
	final double BOUNDARY_THICKNESS = 15;
	static final long serialVersionUID = 1L; 
	ParticleDialog particleDialog;
	JLabel statusLabel = new JLabel();
	ArrayList<MyObject> objects = new ArrayList<MyObject>();
	ArrayList<Wall> walls = new ArrayList<Wall>();
	//Booleans and vars to track wall creation
	boolean walling = false, walling1 = false, walling2 = false;
	double x1, y1, x2, y2, thickness = 5;
	boolean running = true;
	public World()
	{
		super("Momentum Demonstration");
		setFocusable(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setSize(500, 500);
		addKeyListener(this);
		addMouseListener(new MyMouseAdapter());
		add(statusLabel);
		statusLabel.setVisible(true);
		//Init newObjectDialog
		particleDialog = new ParticleDialog(this, "New Object");
		setupBoundaries();
	}
	public void randomizeObjects(int num)
	{
		objects.clear();
		
	}
	public void setupBoundaries()
	{
		walls.add(new Wall(1, 0, getSize().getWidth() + 1, 0, BOUNDARY_THICKNESS));
		walls.add(new Wall(1, 0, 0, getSize().getHeight() + 1, BOUNDARY_THICKNESS));
		walls.add(new Wall(1, getSize().getHeight(), getSize().getWidth() + 1, getSize().getHeight(), BOUNDARY_THICKNESS));
		walls.add(new Wall(getSize().getWidth() + 5, getSize().getHeight(), getSize().getWidth() + 1, 0, BOUNDARY_THICKNESS));
		
	}
	public void setupPair()
	{
		objects.clear();
		objects.add(new MyObject(10, 100, 250, 100,0,0,0));
		objects.add(new MyObject(13, 400, 250, -100,0,0,0));
	}
	public List<MyObject> getObjects()
	{
		return objects;
	}
	public void incrementTime(long millis)//update position using velocity, update velocity using acceleration
	{
		if(running)
		{
			double time = (double) millis / 1000;
			for(MyObject obj: objects)
			{
				obj.x += obj.vX * time;
				obj.y += obj.vY * time;
				obj.vX += obj.aX * time;
				obj.vY += obj.aY * time;
				collideMyObjects(obj);
			}
		}
		
	}
	/**
	 * Helper function of <code>incrementTime()</code>
	 **/
	private void collideMyObjects(MyObject obj)
	{
		//facilitate collisions
		for(MyObject otherObj: objects)
		{
			if(otherObj.equals(obj))
				continue;
			if(obj.checkSphereCollision(otherObj))
			{
				double tempVX, tempVY;
				tempVX = obj.vX;
				tempVY = obj.vY;
				//Temporary mass fix
				if(obj.mass == 0 || otherObj.mass == 0)
				{
					obj.mass = 1;
					otherObj.mass = 1;
				}
				obj.vX = otherObj.vX / obj.mass * otherObj.mass;
				obj.vY = otherObj.vY / obj.mass * otherObj.mass;
				otherObj.vX = tempVX / otherObj.mass * obj.mass;
				otherObj.vY = tempVY / otherObj.mass * obj.mass;
				
			}
			
		}
		for(Wall wall: walls)
		{
			wall.checkParticleCollision(obj);
		}
		
	}
	@Override
	public void keyPressed(java.awt.event.KeyEvent ke) 
	{
		if(ke.getKeyChar() == 'n')
		{
			particleDialog.setVisible(true);
		}
		if(ke.getKeyChar() == 'w')
		{
			if(!walling2)
			{
				walling1 = true;
				statusLabel.setText("Wall start?");
			}
		}
		if(ke.getKeyChar() == 'p')
			running = !running;
	}
	@Override
	public void keyReleased(java.awt.event.KeyEvent e) 
	{
		//Do Nothing
	}
	@Override
	public void keyTyped(java.awt.event.KeyEvent ke) 
	{
		//Do Nothing
	}
	public int addObject(double radius, double x, double y, double xV, double yV, double mass)
	{
		objects.add(new MyObject(radius, x, y, xV, yV, 0, 0).setMass(mass));
		return 0;
	}
	private class MyMouseAdapter extends MouseAdapter
	{
		public void mouseClicked(MouseEvent me)
		{
			if(me.getButton() == MouseEvent.BUTTON1)
			{
				if(walling1)
				{
					x1 = me.getX();
					y1 = me.getY();
					walling2 = true;
					walling1 = false;
					statusLabel.setText("Wall end?");
					return;
				}
				if(walling2)
				{
					x2 = me.getX();
					y2 = me.getY();
					walling2 = false;
					createWall();
					statusLabel.setText("");
					return;
				}
				if(particleDialog.isVisible())
					particleDialog.setParticlePosition(me.getX() - 8D, me.getY() - 28D);//Compensate for borders
			}
		}
		
	}
	/**
	 * TODO: Add collision check before adding wall.
	 **/
	private void createWall()
	{
		Wall wall = new Wall(x1 - 8, y1-28, x2-8, y2-28, thickness);
		for(MyObject obj: objects)
			if(wall.checkParticleCollision(obj))
					return;
		walls.add(new Wall(x1 - 8, y1-28, x2-8, y2-28, thickness));
		
		
	}
}
